#ifndef __COMM_DBG_LOG_H__
#define __COMM_DBG_LOG_H__
#include "comm/comm_data_type.h"
#include "comm/comm_sys.h"
#include "comm/comm_time.h"
#include <mutex>


using namespace std;

extern mutex g_objLogMutex;


#define CHECK_TRUE(condition_)                          ((condition_) ? 0 : -1)
#define CHECK_PTR(ptr_)                                 CHECK_TRUE(ptr_ != NULL)


/**************************************************************************************
功能描述: 普通日志
          日志格式: 线程号        时间   日志类型 函数名 日志信息
          打印后，清除缓存，保证能实时输出，注意其中逗号不要修改成分号，注意使用##去掉变参个数为0时前面的多余的逗号
          为保证多线程下日志输出不乱，需要加锁
修改记录:
**************************************************************************************/
#define ST_LOG(strLogType_, strFmt_, ...)                                       \
    do {                                                                        \
        g_objLogMutex.lock();                                                   \
        printf("[%8x] %s [" strLogType_ "]%s: " strFmt_ "\n",                   \
               UINT32(GetTid()),                                                \
               Comm_GetTimeStr(),                                               \
               Comm_GetFuncName(__PRETTY_FUNCTION__),                           \
               ##__VA_ARGS__);                                                  \
        fflush(stdout);                                                         \
        g_objLogMutex.unlock();                                                 \
    } while (0)

#define ST_LOG_ERR(strFmt_, ...)                ST_LOG("ERR", strFmt_, ##__VA_ARGS__)
#define ST_LOG_INFO(strFmt_, ...)               ST_LOG("INFO", strFmt_, ##__VA_ARGS__)
#define ST_LOG_FATAL(strFmt_, ...)              ST_LOG("FATAL", strFmt_, ##__VA_ARGS__)

/**************************************************************************************
功能描述: 条件日志
修改记录:
**************************************************************************************/
#define ST_IF_LOG_INFO(sw_, strFmt_, ...)       if (sw_) { ST_LOG_INFO(strFmt_, ##__VA_ARGS__); }
#define ST_IF_LOG_ERR(sw_, strFmt_, ...)        if (sw_) { ST_LOG_ERR(strFmt_, ##__VA_ARGS__); }

/**************************************************************************************
功能描述: 采样日志
修改记录:
**************************************************************************************/
#define ST_LOG_SAMPLE(sampleTimes_, strLogType_, strFmt_, ...)      \
    do {                                                            \
        static UINT32 outputTimes_ = sampleTimes_;                  \
        ++outputTimes_;                                             \
        if (outputTimes_ >= (sampleTimes_)) {                       \
            outputTimes_ = 0;                                       \
            ST_LOG(strLogType_, strFmt_, ##__VA_ARGS__);            \
        }                                                           \
    } while(0)

#define ST_LOG_ERR_SAMPLE(sampleTimes_, strFmt_, ...)   ST_LOG_SAMPLE(sampleTimes_, "ERR", strFmt_, ##__VA_ARGS__)
#define ST_LOG_INFO_SAMPLE(sampleTimes_, strFmt_, ...)  ST_LOG_SAMPLE(sampleTimes_, "INFO", strFmt_, ##__VA_ARGS__)

/**************************************************************************************
功能描述: 条件采样日志
修改记录:
**************************************************************************************/
#define ST_LOG_SAMPLE_IF_TRUE(sw_, sampleTimes_, strLogType_, strFmt_, ...)     \
    do {                                                                        \
        static BOOL   swOldVal     = false;                                     \
        static UINT32 outputTimes_ = (sampleTimes_);                            \
        BOOL swNewVal = (sw_);                                                  \
        if (swOldVal != swNewVal) {                                             \
            if (swNewVal) {                                                     \
                ST_LOG(strLogType_, strFmt_ " Begin.", ##__VA_ARGS__);          \
                outputTimes_ = 0;                                               \
            } else {                                                            \
                ST_LOG(strLogType_, strFmt_ " End.", ##__VA_ARGS__);            \
            }                                                                   \
            swOldVal = swNewVal;                                                \
        }                                                                       \
        if (swOldVal) {                                                         \
            ++outputTimes_;                                                     \
            if (outputTimes_ >= (sampleTimes_)) {                               \
                outputTimes_ = 0;                                               \
                ST_LOG(strLogType_, strFmt_, ##__VA_ARGS__);                    \
            }                                                                   \
        }                                                                       \
    } while(0)

#define ST_LOG_INFO_SAMPLE_IF_TRUE(sw_, sampleTimes_, strFmt_, ...)     ST_LOG_SAMPLE_IF_TRUE(sw_, sampleTimes_, "INFO", strFmt_, ##__VA_ARGS__)
#define ST_LOG_ERR_SAMPLE_IF_TRUE(sw_, sampleTimes_, strFmt_, ...)      ST_LOG_SAMPLE_IF_TRUE(sw_, sampleTimes_, "ERR", strFmt_, ##__VA_ARGS__)
#define ST_LOG_ERR_SAMPLE_IF_FAIL(rslt_, sampleTimes_, strFmt_, ...)    ST_LOG_ERR_SAMPLE_IF_TRUE(rslt_ != 0, sampleTimes_, strFmt_, ##__VA_ARGS__)

/**************************************************************************************
功能描述: 智能打印，避免周期频繁打印
修改记录:
**************************************************************************************/
#define ST_LOG_AI(newVal_, printStrWhenSucc_, printStrWhenFail_, printInterContinueTimes_)              \
    do {                                                                                                \
        static BOOL   isSuccPre_     = true;                                                            \
        static UINT32 continueTimes_ = 0;                                                               \
               BOOL   isSuccNow_     = ((newVal_) == 0);                                                \
        ++continueTimes_;                                                                               \
        if (isSuccNow_ == isSuccPre_) {                                                                 \
            if (continueTimes_ > (printInterContinueTimes_)) {                                          \
                if (isSuccNow_) {                                                                       \
                    ST_LOG_INFO(printStrWhenSucc_" Continue %u Times.", printInterContinueTimes_);      \
                } else {                                                                                \
                    ST_LOG_ERR(printStrWhenFail_" Continue %u Times.", printInterContinueTimes_);       \
                }                                                                                       \
                continueTimes_ = 0;                                                                     \
            }                                                                                           \
        } else {                                                                                        \
            if (isSuccNow_) {                                                                           \
                ST_LOG_INFO(printStrWhenSucc_);                                                         \
            } else {                                                                                    \
                ST_LOG_ERR(printStrWhenFail_);                                                          \
            }                                                                                           \
            isSuccPre_     = isSuccNow_;                                                                \
            continueTimes_ = 0;                                                                         \
        }                                                                                               \
    } while (0)

/**************************************************************************************
功能描述: 断言
修改记录:
**************************************************************************************/
#define NOTHING
#define R_ASSERT(condition_, retVal_)                                       if (!(condition_)) { ST_LOG_FATAL("Check(%s) Fail.",                                                                 #condition_);                                                             return retVal_; }
#define R_ASSERT_1(condition_, retVal_, para1_)                             if (!(condition_)) { ST_LOG_FATAL("Check(%s) Fail. "#para1_" = %d.",                                                 #condition_, INT32(para1_));                                              return retVal_; }
#define R_ASSERT_2(condition_, retVal_, para1_, para2_)                     if (!(condition_)) { ST_LOG_FATAL("Check(%s) Fail. "#para1_" = %d, "#para2_" = %d.",                                 #condition_, INT32(para1_), INT32(para2_));                               return retVal_; }
#define R_ASSERT_3(condition_, retVal_, para1_, para2_, para3_)             if (!(condition_)) { ST_LOG_FATAL("Check(%s) Fail. "#para1_" = %d, "#para2_" = %d, "#para3_" = %d.",                 #condition_, INT32(para1_), INT32(para2_), INT32(para3_));                return retVal_; }
#define R_ASSERT_4(condition_, retVal_, para1_, para2_, para3_, para4_)     if (!(condition_)) { ST_LOG_FATAL("Check(%s) Fail. "#para1_" = %d, "#para2_" = %d, "#para3_" = %d, "#para4_" = %d.", #condition_, INT32(para1_), INT32(para2_), INT32(para3_), INT32(para4_)); return retVal_; }


#endif

